<?php
namespace app\admin\library\alei;

use PhpOffice\PhpSpreadsheet\Cell\DataType;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Style\Alignment;
use PhpOffice\PhpSpreadsheet\Style\Border;
use PhpOffice\PhpSpreadsheet\Style\Fill;
use PhpOffice\PhpSpreadsheet\Writer\Xlsx;

/**
 * 导出类
 */
class Export
{
    //导出选项
    private $option = [
        //导出文件路径
        'file_path'                         => '',
        //导出文件名
        'file_name'                         => '导出文件',
        //首行是否加粗
        'header_bold'                       => true,
        //垂直居中
        'header_vertical_center'            => true,
        //水平居中
        'header_horizontal_center'          => true,
        //首列高度
        'header_row_height'                 => 30
    ];

    private $column;

    private $data;

    /**
     * @params Array|String $option_or_file_name 导出选项或者文件名
     * @params String $file_path 文件保存路径
     */
    public function __construct($option_or_file_name = null, $file_path = null)
    {        
        if(!is_null($option_or_file_name)){
            if(is_array($option_or_file_name)) {
                //设置导出选项
                $this->option = array_merge($this->option, $option_or_file_name);
            }else if(is_string($option_or_file_name) && strlen($option_or_file_name) > 0){
                //设置保存的文件名
                $this->option['file_name'] = $option_or_file_name;
            }
        }

        //设置保存的文件路径
        if (!is_null($file_path) && is_string($file_path) && strlen($file_path) > 0) {
            $this->option['file_path'] = $file_path;
        }
    }


    /**
     * 设置列参数
     * @param String field 字段名
     * @param String title 标题
     * @param Int width 列宽
     * @param Function|String formater [格式化器，参数1：字段值，参数2：行数据，参数3：行号] 或 [预定义方法：'time'：格式化时间]
     * @param String type 类型 default 'text'
     * @param Boole vertical_center 是否垂直居中，default false 
     * @param Boole horizontal_center 是否水平居中，default false
     */
    public function setColumn($column)
    {
        $this->column = $column;
    }

    /**
     * 格式化行参数
     */
    private function formatRowData($data)
    {
        $tmp = [];
        foreach ($this->column as $key => $column) {
            if (isset($data[$column['field']])) {
                $tmp[$column['field']] = $data[$column['field']];
            } else {
                $tmp[$column['field']] = '';
            }
            if (isset($column['formater'])) {
                if (gettype($column['formater']) === 'object' && is_callable($column['formater'])) {
                    $tmp[$column['field']] = $column['formater']($tmp[$column['field']], $data, $key);
                } else if (is_string($column['formater'])) {
                    //格式化
                    switch($column['formater']){
                        case 'time': //时间戳转时间
                            $format_time = $column['format_time'] ?? 'Y-m-d H:i:s';
                            if (empty($tmp[$column['field']])) {
                                $tmp[$column['field']] = '';
                            } else {
                                $tmp[$column['field']] = date($format_time, $tmp[$column['field']]);
                            }
                            break;
                        default :
                    }
                }
            }
        }
        return $tmp;
    }


    /**
     * 设置数据
     */
    public function setData($list)
    {
        if (empty($this->column)) throw new \think\Exception('Please set the column parameters first!');
        $data = [];
        foreach ($list as $key => $val) {
            $data[] = $this->formatRowData($val);
            unset($list[$key]);
        }

        $this->data = $data;
    }


    /**
     * 渲染表格并返回
     * @params $column 列参数
     * @params $data 导出数据
     */
    public function build()
    {
        if (empty($this->column)) {
            throw new \think\Exception('Please set the column parameters first!');
        }

        $spreadsheet = new Spreadsheet();
        // 1获取活动工作薄
        $sheet = $spreadsheet->getActiveSheet();

        //最后一列列号
        $end_row = count($this->column);

        // 首行选择器
        $first_cell = [1, 1, $end_row, 1];

        //设置背景色
        $sheet->getStyle($first_cell)->getFill()->setFillType(Fill::FILL_SOLID);
        $sheet->getStyle($first_cell)->getFill()->getStartColor()->setARGB('FFeeeeee');

        //首行加边框
        $sheet->getStyle($first_cell)->getBorders()->applyFromArray([
            'allBorders'   => [
                'borderStyle'   =>  Border::BORDER_HAIR,
                'color' =>   ['argb' => '666666']
            ]
        ]);

        //加粗
        if ($this->option['header_bold']) {
            $sheet->getStyle($first_cell)->getFont()->setBold(true);
        }

        //垂直居中
        if ($this->option['header_vertical_center']) {
            $sheet->getStyle($first_cell)->getAlignment()->setVertical(Alignment::VERTICAL_CENTER);
        }

        //水平居中
        if ($this->option['header_horizontal_center']) {
            $sheet->getStyle($first_cell)->getAlignment()->setHorizontal(Alignment::HORIZONTAL_CENTER);
        }

        //首行高度
        $sheet->getRowDimension(1)->setRowHeight($this->option['header_row_height']);


        foreach ($this->column as $key => $column) {
            $sheet->setCellValue([$key + 1, 1], $column['title']);
            $sheet->getColumnDimensionByColumn($key + 1)->setAutoSize(true);
        }


        foreach ($this->data as $key => $row) {
            foreach ($this->column as $k => $column) {
                $value = $row[$column['field']];
                $cell = [$k + 1, $key + 2];

                //换行
                if (mb_strpos($value, PHP_EOL) !== false) {
                    $sheet->getStyle($cell)->getAlignment()->setWrapText(true);
                }

                //垂直居中
                if (!empty($column['vertical_center'])) {
                    $sheet->getStyle($cell)->getAlignment()->setVertical(Alignment::VERTICAL_CENTER);
                }

                //水平居中
                if (!empty($column['horizontal_center'])) {
                    $sheet->getStyle($cell)->getAlignment()->setHorizontal(Alignment::HORIZONTAL_CENTER);
                }

                //设置文字
                $sheet->setCellValueExplicit($cell, $value, DataType::TYPE_STRING);
            }
            unset($this->data[$key]);
        }


        //设置工作表标题
        $sheet->setTitle($this->option['file_name']);

        $this->option['file_path'] = $this->option['file_path'] == '' ? '' : ($this->option['file_path'] . '/' );

        $url = '/export/' . $this->option['file_path'] . $this->option['file_name'] . '.xlsx';
        $filePath = public_path() . str_replace('/', DIRECTORY_SEPARATOR, $url);

        if( is_file($filePath)){
            //如果文件已经导出过则删除旧文件
            unlink($filePath);//这个括号给我转译了，换成英文版的括号
        }else if (!is_dir(dirname($filePath))) {
            mkdir(dirname($filePath), 0700, true);
        }

        
        // 保存电子表格
        $writer = new Xlsx($spreadsheet);
        $writer->save($filePath);

        return $url;
    }

}